/*
 * Copyright (c) 2022 Hong Jiahua
 * https://gitee.com/arrco/jh_share_deque
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifndef __JH_SHARE_QUEUE_H__
#define __JH_SHARE_QUEUE_H__

#include <string.h>

/************************************************************************/
/*                                                                      */
/************************************************************************/
//游标使用的数据类型
typedef unsigned short jh_cursor_type;

// #define JH_SHARE_QUEUE_DYNAMIC_SPACE

#ifdef JH_SHARE_QUEUE_DYNAMIC_SPACE

#include <stdlib.h>

#define JH_SHARE_QUEUE_MALLOC   malloc
#define JH_SHARE_QUEUE_FREE     free

#endif
/************************************************************************/
/*                                                                      */
/************************************************************************/
#define JH_SHARE_QUEUE_BASE_DATA_SPACE(__type, __len, __name) \
unsigned char __name[(sizeof(__type) + sizeof(jh_cursor_type) * 2) * __len];

/**
  * @brief  双端队列共享的数据空间
  */
#define JH_SHARE_QUEUE_DATA_SPACE(__type, __len, __name, __num) \
    JH_SHARE_QUEUE_BASE_DATA_SPACE(__type, (__len + __num + 1), __name)

/**
  * @brief  共享双端队列数据结构
  */
typedef struct {
    void* base;
    size_t num;
    size_t size;
    size_t item_size;
    size_t offset;
} jh_share_deque_t;

/************************************************************************/
/*                                                                      */
/************************************************************************/
typedef struct {
    jh_cursor_type prev;
    jh_cursor_type next;
} jh_share_deque_base_t;

#define JH_SD_GET(__share_deque, __cursor, __val) ((jh_share_deque_base_t *)((__share_deque)->base + (__cursor) * (__share_deque)->size))->__val
#define JH_SD_ELEMENT_ADDR(__share_deque, __cursor) ((__share_deque)->base + (__cursor) * (__share_deque)->size + (__share_deque)->offset)
#define JH_SD_USE_HEAD(__share_deque, __id) ((__share_deque)->num - __id)
#define JH_SD_IDLE_HEAD    0
#define JH_SD_NULL         0
/************************************************************************/
/*                                                                      */
/************************************************************************/
/**
  * @brief  共享双端队列数据迭代
  */
#define JH_SHARE_QUEUE_ITER(__share_deque, id, item)                                                                                                    \
    for (jh_cursor_type __jh_i = JH_SD_GET((__share_deque), JH_SD_USE_HEAD((__share_deque), id), next);                                                 \
         memcpy((item), JH_SD_ELEMENT_ADDR((__share_deque), __jh_i), (__share_deque)->item_size), (__jh_i) != (JH_SD_USE_HEAD((__share_deque), id));    \
         __jh_i = JH_SD_GET((__share_deque), __jh_i, next))

/**
  * @brief  共享双端队列数据反向迭代
  */
#define JH_SHARE_QUEUE_ITER_REVERSE(__share_deque, id, item)                                                                                            \
    for (jh_cursor_type __jh_i = JH_SD_GET((__share_deque), JH_SD_USE_HEAD((__share_deque), id), prev);                                                 \
         memcpy((item), JH_SD_ELEMENT_ADDR((__share_deque), __jh_i), (__share_deque)->item_size), (__jh_i) != (JH_SD_USE_HEAD((__share_deque), id));    \
         __jh_i = JH_SD_GET((__share_deque), __jh_i, prev))
    
/*判断共享双端队列是否为空*/
int jh_share_deque_is_empty(jh_share_deque_t* share_deque, size_t deque_id);
/*判断共享双端队列是否已满*/
int jh_share_deque_is_full(jh_share_deque_t* share_deque);
/*获取共享双端队列的数据数量*/
size_t jh_share_deque_count(jh_share_deque_t* share_deque, size_t deque_id);
/*数据添加到队首*/
int jh_share_deque_push_head(jh_share_deque_t* share_deque, size_t deque_id, void* item);
/*数据添加到队尾*/
int jh_share_deque_push_tail(jh_share_deque_t* share_deque, size_t deque_id, void* item);
/*队首数据出队*/
int jh_share_deque_pop_head(jh_share_deque_t* share_deque, size_t deque_id, void* item);
/*队尾数据出队*/
int jh_share_deque_pop_tail(jh_share_deque_t* share_deque, size_t deque_id, void* item);
/*查看队首的数据*/
int jh_share_deque_peek_head(jh_share_deque_t* share_deque, size_t deque_id, void* item);
/*查看队尾的数据*/
int jh_share_deque_peek_tail(jh_share_deque_t* share_deque, size_t deque_id, void* item);
/*清空共享双端队列*/
int jh_share_deque_clear(jh_share_deque_t* share_deque, size_t deque_id);
/*获取共享双端队列指定位置的指定数量数据*/
int jh_share_deque_get_data(jh_share_deque_t* share_deque, size_t deque_id, void* item, size_t start, size_t num);
/*共享双端队列初始化*/
int jh_share_deque_init(jh_share_deque_t* share_deque, size_t deque_num, void* base, size_t num, size_t size);
#ifdef JH_SHARE_QUEUE_DYNAMIC_SPACE
/*双端队列共享空间申请*/
int jh_share_deque_space_malloc(jh_share_deque_t* share_deque, size_t deque_num, size_t num, size_t size);
/*双端队列共享空间释放*/
int jh_share_deque_space_free(jh_share_deque_t* share_deque);
#endif

#endif